/**
 * Copyright &copy; 2012-2013 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.chlitina.store.modules.sys.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.subject.Subject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.chlitina.store.common.session.BoTongSessionContext;
import com.chlitina.store.common.utils.DateUtils;
import com.chlitina.store.modules.base.dao.CustomerDao;
import com.chlitina.store.modules.base.dao.CustomerGroupDao;
import com.chlitina.store.modules.base.dao.StoreCareDao;
import com.chlitina.store.modules.base.dao.StoreProductDao;
import com.chlitina.store.modules.base.dao.StoreRoleDao;
import com.chlitina.store.modules.base.entity.Customer;
import com.chlitina.store.modules.base.entity.CustomerGroup;
import com.chlitina.store.modules.base.entity.CustomerGroupDetail;
import com.chlitina.store.modules.base.entity.StoreCardTemplateProduct;
import com.chlitina.store.modules.base.entity.StoreCardTemplateProductDetail;
import com.chlitina.store.modules.base.entity.StoreCare;
import com.chlitina.store.modules.base.entity.StoreProduct;
import com.chlitina.store.modules.base.entity.StoreRole;
import com.chlitina.store.modules.base.service.CustomerGroupDetailService;
import com.chlitina.store.modules.base.service.StoreCardTemplateAllService;
import com.chlitina.store.modules.base.service.StoreCardTemplateDurationService;
import com.chlitina.store.modules.base.service.StoreCardTemplateProductService;
import com.chlitina.store.modules.base.service.StoreCardTemplateTimesService;
import com.chlitina.store.modules.cash.model.CardTemplates;
import com.chlitina.store.modules.cash.model.Member;
import com.chlitina.store.modules.cash.model.ShoppingCart;
import com.chlitina.store.modules.employee.dao.EmployeeDao;
import com.chlitina.store.modules.employee.entity.Employee;
import com.chlitina.store.modules.sys.dao.AreaDao;
import com.chlitina.store.modules.sys.dao.StoreDao;
import com.chlitina.store.modules.sys.dao.StoreMenuDao;
import com.chlitina.store.modules.sys.entity.Area;
import com.chlitina.store.modules.sys.entity.Store;
import com.chlitina.store.modules.sys.entity.StoreMenu;
import com.chlitina.store.modules.sys.entity.StoreType;
import com.chlitina.store.modules.sys.security.LoginSessionToken;
import com.chlitina.store.modules.sys.security.SystemRealm.Principal;
import com.chlitina.store.modules.sys.service.SettingsService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 用户工具类
 * 
 * @author ThinkGem
 * @version 2013-4-21
 */
@Service
public class StoreUtils implements ApplicationContextAware {

	private static StoreDao storeDao;
	private static StoreRoleDao storeRoleDao;
	private static StoreMenuDao storeMenuDao;
	private static AreaDao areaDao;
	private static EmployeeDao employeeDao;
	private static CustomerDao customerDao;
	private static CustomerGroupDao customerGroupDao;
	private static CustomerGroupDetailService customerGroupDetailService;
	private static StoreCareDao storeCareDao;
	private static StoreProductDao storeProductDao;
	private static StoreCardTemplateAllService storeCardTemplateAllService;
	private static StoreCardTemplateDurationService storeCardTemplateDurationService;
	private static StoreCardTemplateProductService storeCardTemplateProductService;
	private static StoreCardTemplateTimesService storeCardTemplateTimesService;
	private static SettingsService settingsService;
	public static Map<Long, List<LoginSessionToken>> allStoreSessionMap;		

	public static Store getStore() {
//		Store store = (Store) getCache("store");
		Store store = null;
		if (store == null) {
			Principal principal = (Principal) SecurityUtils.getSubject()
					.getPrincipal();
			if (principal != null) {
				store = storeDao.getByName(principal.getLoginName());
				putCache("store", store);
			}
		}
		if (store == null) {
			store = new Store();
			SecurityUtils.getSubject().logout();
		}
		return store;
	}

	public static Member getMember() {
		Member member = (Member) getCache("member");
		return member;
	}

	public static void setMember(Member member){
		putCache("member", member);
	}
	
	public static void removeMember(){
		removeCache("member");
	}
	
	public static Integer getSessionTimeout(){
		Integer timeout = (Integer)getCache("sessionTimeout");
		if (timeout == null || timeout == 0) {
			timeout = settingsService.getIntValue("SESSION_TIMEOUT");
			setSessionTimeout(timeout);
		}
		return timeout;
	}
	
	public static void setSessionTimeout(Integer value){
		putCache("sessionTimeout", value);
	}
	
	public static CardTemplates getCardTemplates() {
		CardTemplates templates = (CardTemplates) getCache("cardTemplates");
		if (templates == null) {
			templates = new CardTemplates();
			templates.setAllCardTemplates(storeCardTemplateAllService
					.getByStore());
			templates.setDurationCardTemplates(storeCardTemplateDurationService
					.getByStore());
			templates.setProductCardTemplates(storeCardTemplateProductService
					.getByStore());

			//should list output details, otherwise, some error may happen on LAZYLOADING
			for (StoreCardTemplateProduct template : templates.getProductCardTemplates()) {
				List<StoreCardTemplateProductDetail> productList = template.getProductList();
				for (StoreCardTemplateProductDetail storeCardTemplateProductDetail : productList) {
					System.out.println(storeCardTemplateProductDetail);
				}
			}
			templates.setTimesCardTemplates(storeCardTemplateTimesService
					.getByStore());
			putCache("templates", templates);
		}
		return templates;
	}

	public static ShoppingCart getShoppingCart() {
		ShoppingCart shoppingCart = (ShoppingCart) getCache("shoppingCart");
		if (shoppingCart == null) {
			shoppingCart = new ShoppingCart();
			putCache("shoppingCart", shoppingCart);
		}
		return shoppingCart;
	}

	public static Store getStore(boolean isRefresh) {
		if (isRefresh) {
			removeCache("store");
		}
		return getStore();
	}

	public static String getLoginPw() {
		Store store = getStore();
		if (store.getNeed_login_pw() == Store.NONEED_LOGIN_PW) {
			return "";
		}
		return getStore().getLoginPassword();
	}

	public static boolean isEditable(String parent) {
		boolean hasSystemSetting = false;
		List<StoreMenu> menuList = StoreUtils.getMenuList2();
		for (StoreMenu storeMenu : menuList) {
			if ("系统设置".equals(storeMenu.getName())) {
				hasSystemSetting = true;
				continue;
			}
			if (hasSystemSetting) {
				if (!"修改".equals(storeMenu.getName())) {
					continue;
				} else {
					int index = menuList.indexOf(storeMenu);
					for (int i = index - 1; i > -1 && i > index - 3; i--) {
						if (menuList.get(i).getName().equals(parent)) {
							return true;
						}
					}
				}
			}
		}
		return false;
	}

	public static StoreRole getStoreRole(Long id) {
		return storeRoleDao.findOne(id);
	}

	public static Map<Long, String> getStoreRoleList() {
		Map<Long, String> roleMap = Maps.newHashMap();
		@SuppressWarnings("unchecked")
		List<StoreRole> roleList = (List<StoreRole>) getCache("roleList");
		if (roleList == null) {
			roleList = storeRoleDao.findAllList();
			putCache("roleList", roleList);
		}
		for (StoreRole sr : roleList) {
			roleMap.put(sr.getId(), sr.getName());
		}
		return roleMap;
	}

	/**
	 * 获取一个客户群的所有成员
	 * 
	 * @return
	 */
	public static List<CustomerGroupDetail> getCustomerGroupNumber(Long id) {
		List<CustomerGroupDetail> list = customerGroupDetailService.getByGroupId(id);
		if (list == null) {
			return Lists.newArrayList();
		}
		return list;
	}
	/**
	 * 获取一个店面的所有店员List
	 * 
	 * @return
	 */
	public static List<Employee> getStoreEmployees() {
		@SuppressWarnings("unchecked")
		List<Employee> employeeList = (List<Employee>) getCache("employeeList");
		if (employeeList == null || employeeList.size() > 0) {
			Store store = getStore();
			employeeList = employeeDao.findListByStore(store.getId());
		}
		return employeeList;
	}

	/**
	 * 获取一个店面的所有店员Map
	 * 
	 * @return
	 */
	public static Map<Long, String> getStoreEmployeeList() {
		Map<Long, String> employeeMap = Maps.newHashMap();
		List<Employee> employeeList = getStoreEmployees();
		for (Employee e : employeeList) {
			employeeMap.put(e.getId(), e.getName());
		}
		return employeeMap;
	}

	/**
	 * 获取一个店面的所有客户List集合
	 * 
	 * @return
	 */
	public static List<Customer> getStoreCustomers() {
		@SuppressWarnings("unchecked")
		List<Customer> customerList = (List<Customer>) getCache("customerList");
		if (customerList == null || customerList.size() == 0) {
			Store store = getStore();
			customerList = customerDao.findListByStore(store.getId());
		}
		return customerList;
	}

	/**
	 * 获取一个店面的所有客户Map集合
	 * 
	 * @return
	 */
	public static Map<Long, String> getStoreCustomerList() {
		Map<Long, String> customerMap = Maps.newHashMap();
		List<Customer> customerList = getStoreCustomers();
		for (Customer c : customerList) {
			customerMap.put(c.getId(), c.getName() + "(" + c.getMobile() + ")");
		}
		return customerMap;
	}

	/**
	 * 获取一个店面的所有客户Map集合
	 * 
	 * @return
	 */
	public static Map<Long, String> getCustomerMap() {
		Map<Long, String> customerMap = Maps.newHashMap();
		List<Customer> customerList = getStoreCustomers();
		for (Customer c : customerList) {
			customerMap.put(c.getId(), c.getName());
		}
		return customerMap;
	}

	/**
	 * 获取当前门店产品Map集合
	 * 
	 * @return
	 */
	public static Map<Long, String> getStoreProductMap() {
		Store store = getStore();
		Map<Long, String> customerMap = Maps.newHashMap();
		List<StoreProduct> list = storeProductDao
				.findListByStore(store.getId());
		for (StoreProduct c : list) {
			if (c.getProduct_type() == StoreProduct.TYPE_SELF) {
				customerMap.put(c.getId(), c.getStoreSelfProduct().getName());
			}
			if (c.getProduct_type() == StoreProduct.TYPE_SYS) {
				customerMap.put(c.getId(), c.getProduct().getName());
			}
		}
		return customerMap;
	}

	/**
	 * 获取当前门店护理Map集合
	 * 
	 * @return
	 */
	public static Map<Long, String> getStoreCareMap() {
		Store store = getStore();
		Map<Long, String> customerMap = Maps.newHashMap();
		List<StoreCare> list = storeCareDao.findListByStore(store.getId());
		for (StoreCare c : list) {
			// customerMap.put(c.getId(), c.getName());
		}
		return customerMap;
	}

	/**
	 * 获取某个店面的不在某个分组的全部客户
	 * 
	 * @return
	 */
	public static Map<Long, String> getGroupCustomerList(String groupId) {
		Map<Long, String> customerMap = Maps.newHashMap();
		Store store = getStore();
		CustomerGroup customerGroup = customerGroupDao.findOne(Long
				.parseLong(groupId));
		List<CustomerGroupDetail> customerGroupDetailList = customerGroup
				.getCustomerGroupDetailList();
		List<Customer> customerList = customerDao
				.findListByStore(store.getId());
		if (customerList != null && customerList.size() > 0) {
			for (Customer c : customerList) {
				boolean isExist = false;
				for (CustomerGroupDetail cgd : customerGroupDetailList) {
					if (cgd.getCustomer().getId().equals(c.getId())) {
						isExist = true;
					}
				}
				if (!isExist) {
					customerMap.put(c.getId(), c.getName());
				}
			}
		}
		return customerMap;
	}

	@SuppressWarnings("unchecked")
	public static List<StoreMenu> getMenuList() {
		Store store = getStore();
		StoreType storeType = store.getStoreType();
//		List<StoreMenu> menuList = (List<StoreMenu>) getCache("menuList");
		List<StoreMenu> menuList = Lists.newArrayList();
		if (menuList.size() == 0) {
			menuList = storeMenuDao.findByStoreType(storeType.getId());
//			putCache("menuList", menuList);
		}
		return menuList;
	}

	public static List<StoreMenu> getMenuList2() {
		Store store = getStore();
		StoreType storeType = store.getStoreType();
		return storeMenuDao.findValidByStoreType(storeType.getId());
	}

	public static List<StoreMenu> getPathList(String id) {
		List<StoreMenu> pathList = new ArrayList<StoreMenu>();
		List<StoreMenu> menuList = getMenuList();
		StoreMenu target = null;
		for (StoreMenu item : menuList) {
			if (item.getId().toString().equals(id)) {
				target = item;
			}
		}
		while (target != null && target.getId() != 1) {
			pathList.add(target);
			target = target.getParent();
		}
		Collections.reverse(pathList);
		return pathList;
	}

	public static List<Area> getAreaList() {
		@SuppressWarnings("unchecked")
		List<Area> areaList = (List<Area>) getCache("areaList");
		if (areaList == null) {
			areaList = areaDao.findAllList();
			putCache("areaList", areaList);
		}
		return areaList;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		storeDao = (StoreDao) applicationContext.getBean("storeDao");
		storeMenuDao = (StoreMenuDao) applicationContext
				.getBean("storeMenuDao");
		areaDao = (AreaDao) applicationContext.getBean("areaDao");
		storeRoleDao = (StoreRoleDao) applicationContext
				.getBean("storeRoleDao");
		employeeDao = (EmployeeDao) applicationContext.getBean("employeeDao");
		customerDao = (CustomerDao) applicationContext.getBean("customerDao");
		customerGroupDao = (CustomerGroupDao) applicationContext
				.getBean("customerGroupDao");
		customerGroupDetailService = (CustomerGroupDetailService) applicationContext
				.getBean("customerGroupDetailService");
		storeCareDao = (StoreCareDao) applicationContext
				.getBean("storeCareDao");
		storeProductDao = (StoreProductDao) applicationContext
				.getBean("storeProductDao");

		storeCardTemplateAllService = (StoreCardTemplateAllService) applicationContext
				.getBean("storeCardTemplateAllService");
		storeCardTemplateDurationService = (StoreCardTemplateDurationService) applicationContext
				.getBean("storeCardTemplateDurationService");
		storeCardTemplateProductService = (StoreCardTemplateProductService) applicationContext
				.getBean("storeCardTemplateProductService");
		storeCardTemplateTimesService = (StoreCardTemplateTimesService) applicationContext
				.getBean("storeCardTemplateTimesService");
		settingsService = (SettingsService) applicationContext
				.getBean("settingsService");

	}
	//获取request 的target ip
	public static String getIpAddr(HttpServletRequest request) {      
		String ip = request.getHeader("x-forwarded-for");      
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
			ip = request.getHeader("Proxy-Client-IP");      
		}      
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
			ip = request.getHeader("WL-Proxy-Client-IP");      
		}      
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
			ip = request.getRemoteAddr();      
		}      
		return ip;      
	}
	//=================获取一个店面当前登陆的数量===================
	public static String isAllowLogin(String loginName,String password, String sessionId){
		Store store = storeDao.getByName(loginName);
		if (store == null || store.getId() == null) {
			return "登录名不存在!";
		}
		if (password == null || "".equals(password)) {
			return "密码不能为空";
		}
		if (!password.equals(store.getLoginPassword())) {
			return "密码不正确";
		}
		Date endDate = DateUtils.getBeginOfDay(store.getEnd_date());
		Date nowDate = DateUtils.getBeginOfDay(new Date());
		if (endDate.getTime() < nowDate.getTime()) {
			return "店面到期,请续费!";
		}
		Long storeId = store.getId();
		if (allStoreSessionMap == null) {
			allStoreSessionMap = Maps.newHashMap();
		}
		List<LoginSessionToken> list = allStoreSessionMap.get(storeId);
		if (list == null) {
			list = Lists.newArrayList();
		}
		int amount = list.size();
		if (amount < store.getAllow_amount()) {
			HttpSession session = BoTongSessionContext.getInstance().getSession(sessionId);
			if (session != null) {
				LoginSessionToken loginSession = new LoginSessionToken(sessionId);
				list.add(loginSession);
				allStoreSessionMap.put(storeId, list);
				return "true";
			}
		}
		LoginSessionToken removeSession = null;
		long currentTimeMillis = System.currentTimeMillis();
		Integer sessionTimeout = getSessionTimeout();
		long timeoutMillis = sessionTimeout * 60 * 1000;
		for (LoginSessionToken loginSessionToken : list) {
			String sessionTokenId = loginSessionToken.getSessionId();
			HttpSession session = BoTongSessionContext.getInstance().getSession(sessionTokenId);
			if (session == null) {
				removeSession = loginSessionToken;
				break;
			}
			Long lastOptionTime = session.getLastAccessedTime();
			if (currentTimeMillis - lastOptionTime > timeoutMillis) {
				if (session != null) {
					session.invalidate();
					removeSession = loginSessionToken;
					break;
				}
			}
		}
		if (removeSession != null) {
			list.remove(removeSession);
			LoginSessionToken loginSession = new LoginSessionToken(sessionId);
			list.add(loginSession);
			allStoreSessionMap.put(storeId, list);
			return "true";
		}
		return "登陆数量已满!";
	}
	public static void sessionLogout(String sessionId){
		if (allStoreSessionMap != null) {
			Long storeId = getStore().getId();
			List<LoginSessionToken> list = allStoreSessionMap.get(storeId);
			LoginSessionToken logoutSession = null;
			if (list != null && list.size() > 0) {
				for (LoginSessionToken loginSessionToken : list) {
					if (loginSessionToken.getSessionId().equals(sessionId)) {
						logoutSession = loginSessionToken;
						break;
					}
				}
			}
			if (logoutSession != null) {
				HttpSession session = BoTongSessionContext.getInstance().getSession(logoutSession.getSessionId());
				if (session != null) {
					session.invalidate();
				}
				list.remove(logoutSession);
				allStoreSessionMap.put(storeId, list);
			}
		}
	}
	public static void removeBySessionId(String sessionId){
		if (allStoreSessionMap != null) {
			Set<Long> keySet = allStoreSessionMap.keySet();
			Iterator<Long> iterator = keySet.iterator();
			while (iterator.hasNext()) {
				Long key = iterator.next();
				List<LoginSessionToken> list = allStoreSessionMap.get(key);
				if (list != null && list.size() > 0) {
					LoginSessionToken removeSessionToken = null;
					for (LoginSessionToken loginSessionToken : list) {
						if (loginSessionToken.getSessionId().equals(sessionId)) {
							removeSessionToken = loginSessionToken;
							break;
						}
					}
					if (removeSessionToken != null) {
						list.remove(removeSessionToken);
						allStoreSessionMap.put(key, list);
					}
				}
			}
		}
	}
	//=============== 清除用户自定义的key =====================
	public static void lookUpSessionData(HttpSession session){
		Enumeration<?> names = session.getAttributeNames();
		System.out.println("sessionid"+ session.getId());
		while (names.hasMoreElements()) {
			String key = names.nextElement().toString();
			System.err.println("key:" + key + "  value:" + session.getAttribute(key));
		}
	}
	// ============== User Cache ==============

	public static Object getCache(String key) {
		return getCache(key, null);
	}

	public static Object getCache(String key, Object defaultValue) {
		Object obj = getCacheMap().get(key);
		return obj == defaultValue ? defaultValue : obj;
	}

	public static void putCache(String key, Object value) {
		getCacheMap().put(key, value);
	}

	public static void removeCache(String key) {
		getCacheMap().remove(key);
	}

	private static Map<String, Object> getCacheMap() {
		Map<String, Object> map = Maps.newHashMap();
		try {
			Subject subject = SecurityUtils.getSubject();
			Principal principal = (Principal) subject.getPrincipal();
			return principal != null ? principal.getCacheMap() : map;
		} catch (UnavailableSecurityManagerException e) {
			return map;
		}
	}
}
